package com.YCH.login.service.Impl;

import com.YCH.login.service.TbUserRegisterService;
import com.YCH.model.common.dtos.ResponseResult;
import com.YCH.model.common.enums.AppHttpCodeEnum;
import com.YCH.model.mappers.app.TbUserExperienceMapper;
import com.YCH.model.mappers.app.TbUserMapper;
import com.YCH.model.user.dtos.registerDto;
import com.YCH.model.user.pojos.TbUser;
import com.YCH.model.user.pojos.TbUserExperience;
import com.YCH.model.user.pojos.TbUserLv;
import com.YCH.utils.common.UuidUtil;
import com.YCH.utils.common.VerifyImageUtil;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;


import java.io.File;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static jdk.nashorn.internal.objects.NativeMath.log;

@Log4j2
@Service
@SuppressWarnings("all")
public class TbUserRegisterServiceImpl implements TbUserRegisterService {
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    TbUserMapper tbUserMapper;
    @Autowired
    TbUserExperienceMapper tbUserExperienceMapper;
    private static final Integer EXPERIENCE = 0;
    /**
     * 注册
     * @param dto
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public ResponseResult register(registerDto dto) {
        if(dto.getEmail()==null || dto.getPassword()==null || dto.getPassword2() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }if(!dto.getPassword().equals(dto.getPassword2())){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"两次密码不一样");
        }
        // 校验邮箱验证码
        ResponseResult responseResult = checkEmailCode(dto);
        if(!(responseResult.getCode() == 0)){
            return responseResult;
        }
        // 校验成功，则注册
        TbUser tbUser = new TbUser();
        tbUser.setEmail(dto.getEmail());
        tbUser.setUsername(dto.getEmail());
        tbUser.setPassword(dto.getPassword());
        TbUserLv tbUserLv = new TbUserLv();
        tbUserLv.setId(1);
        tbUser.setLv(tbUserLv);
        tbUser.setCreatTime(new Date());
        Integer insert = tbUserMapper.insert(tbUser);
        if (insert!=1){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
        Integer insert1 = tbUserExperienceMapper.insert(tbUser.getId(), EXPERIENCE, new Date());
        if (insert1!=1){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }


    /**
     * 校验邮箱验证码
     * @param dto
     * @return
     */
    @Override
    public ResponseResult checkEmailCode(registerDto dto) {
        if(dto.getUuid()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        BoundValueOperations boundValueOperations = redisTemplate.boundValueOps(dto.getUuid());
        String code = (String) boundValueOperations.get();
        if (!dto.getCode().equals(code)){
            // 如果验证码不相等，则返回错误
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"验证码错误（注意大小写）或验证码已过期，请重新再试！");
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    private static final String IMG_PATH = "/image/picture/*.*";

    private static final String TEMP_IMG_PATH = "/image/temp/*.*";

    private static final Long IMG_CACHE_EX_TIME = 120L;

    /**
     * 获取图片，由于spring boot打包成jar之后，获取到获取不到resources里头的图片，对此进行处理
     * @param path
     * @return
     * @author pangxianhe
     * @date 2020年1月2日
     */
    public List<File> queryFileList(String path) {

        //获取容器资源解析器
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        List<File> filelist = new ArrayList<File>();
        // 获取远程服务器IP和端口
        try {
            //获取所有匹配的文件(本项目中的resource文件)
            Resource[] resources = resolver.getResources(path);

            for(Resource resource : resources) {
                //获得文件流，因为在jar文件中，不能直接通过文件资源路径拿到文件，但是可以在jar包中拿到文件流
                InputStream stream = resource.getInputStream();
                String targetFilePath =resource.getFilename();
                File ttfFile = new File(targetFilePath);
               /* if(!ttfFile.getParentFile().exists()) {
                	ttfFile.getParentFile().mkdir();
                }*/
                FileUtils.copyInputStreamToFile(stream, ttfFile);
                filelist.add(ttfFile);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        return filelist;
    }

    /**
     * 获取验证码
     * @return
     * @throws Exception
     * @author pangxianhe
     * @date 2020年1月2日
     */
    @Override
    public ResponseResult getImageVerifyCode() {
        // 读取图库目录
        List<File> imgList = queryFileList(IMG_PATH);
        int randNum = new Random().nextInt(imgList.size());
        File targetFile = imgList.get(randNum);
        List<File> tempimgList = queryFileList(TEMP_IMG_PATH);
        File tempImgFile = tempimgList.get(0);
        // 根据模板裁剪图片

        Map<String, Object> resultMap = null;
        try {
            resultMap = VerifyImageUtil.pictureTemplatesCut(tempImgFile, targetFile);
        } catch (Exception e) {
            e.printStackTrace();
            log("切割图片失败 {}",new Date());
        }
        int xWidth = (int) resultMap.get("xWidth");
        // sessionId 为key，value滑动距离X轴，缓存120秒
        // redisTemplate.(session.getId(), xWidth, IMG_CACHE_EX_TIME);
        String chenckMoveid = UuidUtil.getUuid();

        BoundValueOperations<String, Object> redisOper = redisTemplate.boundValueOps(chenckMoveid);
        redisOper.set(xWidth, IMG_CACHE_EX_TIME, TimeUnit.SECONDS);
        // 移除map的滑动距离，不返回给前端
        resultMap.remove("xWidth");
        resultMap.put("chenckMoveid", chenckMoveid);
        return ResponseResult.okResult(resultMap);
    }
}
